﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	EntityMapper.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Diagnostics;
using Smart.Common.Entities.Mapper;

namespace Smart.Common.Entities
{
	/// <summary>
	/// Entity Mapper base
	/// </summary>
	[DebuggerStepThrough]
	public abstract class EntityMapper : IEntityMapper
	{
		protected virtual FieldMapperCacheList ReadCache(string typeName, Type et)
		{
			return EntityMapperExts.ReadCacheMeta(typeName, et);
		}

#if CACHE_LAST_MAPPER
		[ThreadStatic]
		private static volatile Type _lastEntityType;
		[ThreadStatic]
		private static volatile IEntityMapper _lastEntityMapper;
#endif

		public virtual IEntityMapper GetGeneratedMapper(string typeName, Type et)
		{
			return EntityMapperExts.ReadCacheMapper(typeName, et, GetConfig);
		}

		public virtual Entity CreateEntity(Type entityType)
		{
#if CACHE_LAST_MAPPER
			var let = _lastEntityType;
			var lem = _lastEntityMapper;

			if (let == entityType)
				return lem.CreateEntity(entityType);
#endif

			var mapper = GetGeneratedMapper(entityType.FullName, entityType);

#if CACHE_LAST_MAPPER
			_lastEntityType = entityType;
			_lastEntityMapper = mapper;
#endif

			return mapper.CreateEntity(entityType);
		}

		public virtual bool FillEntity(Entity entity)
		{
			var et = entity.GetType();

#if CACHE_LAST_MAPPER
			var let = _lastEntityType;
			var lem = _lastEntityMapper;

			if (let == et)
				return lem.FillEntity(entity);
#endif

			var mapper = GetGeneratedMapper(et.FullName, et);

#if CACHE_LAST_MAPPER
			_lastEntityType = et;
			_lastEntityMapper = mapper;
#endif

			return mapper.FillEntity(entity);
		}

		public virtual bool LoadEntity(object source, Entity entity)
		{
			var et = entity.GetType();

#if CACHE_LAST_MAPPER
			var let = _lastEntityType;
			var lem = _lastEntityMapper;

			if (let == et)
				return lem.LoadEntity(source, entity);
#endif

			var mapper = GetGeneratedMapper(et.FullName, et);

#if CACHE_LAST_MAPPER
			_lastEntityType = et;
			_lastEntityMapper = mapper;
#endif

			return mapper.LoadEntity(source, entity);
		}

		public virtual bool SaveEntity(Entity entity, object source)
		{
			var et = entity.GetType();

#if CACHE_LAST_MAPPER
			var let = _lastEntityType;
			var lem = _lastEntityMapper;

			if (let == et)
				return lem.SaveEntity(entity, source);
#endif

			var mapper = GetGeneratedMapper(et.FullName, et);

#if CACHE_LAST_MAPPER
			_lastEntityType = et;
			_lastEntityMapper = mapper;
#endif

			return mapper.SaveEntity(entity, source);
		}

		public abstract MapperClassBuilderConfig GetConfig();
	}
}